/////////////////////////////////////////////////////////////////////////////
// Name:        imagecache.h
// Purpose:     A class for saving thumbnails for visited directories
// Author:      Julian Smart
// Modified by:
// Created:     2006-05-11
// RCS-ID:      $$
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _WX_IMAGECACHE_H_
#define _WX_IMAGECACHE_H_

#include "wx/defs.h"
#include "wx/image.h"
#include "imageutils/imageblock.h"

/*

1. The app creates a wxImageCache that persists
for the lifetime of the app. Sets the cache folder,
and loads the index.

2. Showing an image browser:

i)   when a folder is about to be shown, instead of reading
     the images immediately, try to load the cache for this folder.
     Load the cache index if it's been modified since last load.
ii)  If found, load cache and throw away any out of date
     items or items with the wrong size.
iii) in idle time or timer callback, check each image file in folder.
     If in cache, display cached bitmap. If not, load image and
     add thumbnail to cache and display.
iv)  When scanning has finished (user intervention or no more files),
     if there are items in the cache, save the cache, and index in case
     of a crash, get file modification date so we know not to load it immediately.


  */

class WXDLLIMPEXP_BASE wxDataInputStream;
class WXDLLIMPEXP_BASE wxDataOutputStream;

// In future we might want to store other kinds of item

#define wxIMAGE_CACHE_TYPE_IMAGE    1

// File format version
#define wxIMAGE_CACHE_FILE_VERSION  1

/*
 * wxImageCacheItem: an item in a folder cache
 */

class wxImageCacheItem: public wxObject
{
public:
    wxImageCacheItem() { Init(); }

    void Init() {};

    void MakeFromImage(const wxImage& image, const wxString& filename, const wxSize& sz = wxDefaultSize);

    wxImageBlock    m_imageBlock;
    wxString        m_filename;
    wxDateTime      m_lastUpdated;
    wxSize          m_size;
};

/*
 * wxImageCache: a class for maintaining a cache of folders visited by
 * an image browser
 */

class wxImageCache: public wxObject
{
    DECLARE_CLASS(wxImageCache)
public:
    wxImageCache() { Init(); }
    ~wxImageCache() { Clear(); }

    /// Initialize members
    void Init();

    /// Clear cache and index
    void Clear();

    /// Clear current cache (resets internal storage for one folder)
    void ClearCache();

    /// Clear index
    void ClearIndex();

    /// Delete all cache files
    void ClearAllCacheFiles();

    /// Loads the cache items for this folder, if any. If there are
    /// no cached items, will set the current folder in case
    /// new items are added.
    bool LoadFolderCache(const wxString& folder, bool force = false);

    /// Loads the cache index, if any
    bool LoadCacheIndex(bool force = false);

    /// Saves the current cache items for this folder, if any
    bool SaveFolderCache();

    /// Saves the cache index, if necessary
    bool SaveCacheIndex();

    /// Adds a cache item
    bool AddCacheItem(wxImageCacheItem* item);

    /// Adds a cache image
    bool AddCacheItem(const wxImage& image, const wxString& filename, const wxSize& sz);

    /// Creates a new cache, and marks the cache as modified.
    /// Index won't be updated until UpdateCache is called.
    bool NewCache(const wxString& folder);

    /// Saves the current folder cache (if modified) and index.
    bool UpdateCache();

    /// Purges the current cache of any items that are out of date w.r.t.
    /// the file on disk, or are a different size from that specified.
    bool PurgeCache(const wxSize& sz = wxDefaultSize);

    //// Find a cache item by its filename
    wxImageCacheItem* FindCacheItem(const wxString& filename);

    //// Remove a cache item from list and delete
    void DeleteCacheItem(wxImageCacheItem* item);

//// Accessors
    
    /// Set the cache storage folder
    void SetCacheStorageFolder(const wxString& folder) { m_cacheStorageFolder = folder; }

    /// Get the cache folder
    const wxString& GetCacheStorageFolder() const { return m_cacheStorageFolder; }

    /// Set the cache folder as the default directory for temporary files
    void SetCacheStorageFolderFromTemp();

    /// Set the current cache folder
    void SetCurrentCacheFolder(const wxString& folder);

    /// Get the current cache folder
    const wxString& GetCurrentCacheFolder() const { return m_currentFolder; }

    /// Is a cache loaded?
    bool IsCacheLoaded() const { return !m_currentFolder.IsEmpty(); }

    /// Mark current folder cache as modified or not
    void SetModified(bool mod) { m_modified = mod; }

    /// Have modifications been made?
    bool IsModified() const { return m_modified; }

    /// Mark index as modified or not
    void SetIndexModified(bool mod) { m_indexModified = mod; }

    /// Set the index custom name
    void SetIndexName(const wxString& name) { m_indexName = name; }

    /// Whether the cache is enabled
    void Enable(bool enable) { m_enabled = enable; }

    /// Have index modifications been made?
    bool IsIndexModified() const { return m_indexModified; }

    /// Get the index filename
    wxString GetIndexFilename() const;

    /// Get the index filename root
    wxString GetIndexName() const { return m_indexName; }

    /// Get the filename for the current folder cache
    wxString GetCacheFilename() const;

    /// Get full path (where the image actually is)
    wxString GetFullPath(const wxString& filename) const;

    /// Get full cache path (in the cache folder)
    wxString GetFullCachePath(const wxString& filename) const;

    /// Whether the cache is enabled
    bool IsEnabled() const { return m_enabled; }

/// Implementation

    /// Has the file been modified since this time?
    bool ModifiedMoreRecently(const wxDateTime& date, const wxString& filename);

    /// Get the modification time
    wxDateTime GetModificationTime(const wxString& filename);

    /// Get a suitable temporary directory
    wxString GetTempDir() const;

    /// Make a new filename for the given folder
    wxString MakeNewCacheFilename(const wxString& folder) const;

    /// Add the folder to the index if necessary
    void AddToIndex(const wxString& folder);

protected:
    /// Where the index and cache files are stored
    wxString    m_cacheStorageFolder;

    /// Current folder, where m_cacheItems refer to this folder
    wxString    m_currentFolder;

    /// Date of the last index file load
    wxDateTime  m_indexLoaded;

    /// The cache items for the current folder
    wxList      m_cacheItems;

    /// Cache index folders
    wxArrayString m_indexFolders;

    /// Cache index cache file paths
    wxArrayString m_indexPaths;

    /// Maximum number of folders to store in cache
    int         m_maxCachedFolders;

    /// Whether we may have a folder cache to save
    bool        m_modified;

    /// Whether the index itself has been modified
    bool        m_indexModified;

    /// Whether the cache is enabled
    bool        m_enabled;

    /// Custom index cache name
    wxString    m_indexName;
};

#endif
    // _WX_IMAGECACHE_H_
